package com.atguigu.gulimall.order.controller;

import com.atguigu.gulimall.order.entity.OrderOperateHistoryEntity;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
public class MyRabbitMQController {

    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * RabbitMQ
     * 发送消息
     *
     * @param num 发送num条消息
     * @return
     */
    @GetMapping("/sendMessage")
    public String sendMessage(@RequestParam(value = "num", required = false, defaultValue = "3") Integer num) {
        for (int i = 0; i < num; i++) {
            OrderOperateHistoryEntity msg = new OrderOperateHistoryEntity();
            msg.setOperateMan(i + "号订单");
            msg.setId((long) i);
            /**
             * 参数1：指定交换器
             * 参数2：指定路由键
             * 参数3：指定消息本身（任意类型都可以，该方法会自动序列化。如果是个对象，注意要实现序列化接口。）
             * 参数4：一些参数(当前消息的唯一id...)
             */
            rabbitTemplate.convertAndSend("hello-java-exchange", "hello.java", msg, new CorrelationData(UUID.randomUUID().toString()));
        }
        return "ok";
    }


    /**
     * RabbitMQ
     * 接收消息（监听消息队列）
     *
     * @RabbitListener(queues={}) 监听指定的消息队列
     * <p>
     * 在当前方法的声明部分，通过形参接收监听到的消息
     * 形参可以有以下类型：
     * ①Message message；原生消息的详细信息，包含消息头+消息体
     * ②T<发送的消息的实际类型>; (发送消息时是什么类型，这里就以什么类型接受，会自动converter)
     * ③Channel channel; 当前传输消息的信道（可用于手动ack）
     */
    @RabbitListener(queues = {"hello-java-queue"})
    public void recieveMessage(Message message, OrderOperateHistoryEntity entity, Channel channel) {

        //1、监听到的消息
        System.out.println("-----监听到的消息->" + message + "---消息的具体内容->" + entity);

        //2、手动确认消息，ack
        long deliveryTag = message.getMessageProperties().getDeliveryTag();//deliveryTag是Channel信道内按顺序自增的一个数据，用来标识每个消息
        try {
            if (deliveryTag % 2 == 0) {
                //只签收deliveryTag为偶数的消息
                /**
                 * 参数1：deliveryTag
                 * 参数2：是否批量模式
                 * 签收deliveryTag这个消息,非批量模式（签收后，服务器会删除这个消息）
                 */
                channel.basicAck(deliveryTag, false);
            } else {
                /**
                 * 参数1：deliveryTag
                 * 参数2：是否批量模式
                 * 参数3：服务器端是否让该消息重新入队 （注意：消息重新入队，会导致该消息一直被监听到。直到签收或丢弃）
                 * 不签收deliveryTag这个消息，非批量模式，不重新入队这个消息（服务器端不会重新入队这个消息，该消息会被删除）
                 */
                //退货，不签收消息
                channel.basicNack(deliveryTag, false, false);
            }
        } catch (Exception ex) {
            //网络中断
        }
    }


}
